/**
 * Copyright (c) 2007, Blue Hole Software. All rights reserved.
 * Code licensed under the Apache 2.0 License:
 * http://www.apache.org/licenses/
 */

package org.bhf.service;

import org.bhf.json.JSONTransient;

import java.util.Random;

/**
 * As a convenience, <code>Component</code>s may extend this class as a means of satisfying the
 * <code>Component</code> contract. <code>Component</code>s are single threaded.
 * @see Component
 */

public class AbstractComponent implements Component
{
    private static Random idGenerator = new Random();

    private int     version = 0;
    private long    id;
    private boolean changed = true;// Assume that we have changed state: conservative

    {
        synchronized( AbstractComponent.class )
        {
            // Truncate so it will work with a JS number type (internally a double)
            this.id = idGenerator.nextLong() & 0x000fffffffffffffL;
        }
    }

    /**
     * Return the current state version of this <code>Component</code>. Each state change, whether client or
     * server side, must increment the version of the state.
     * @return The current state version of this <code>Component</code>.
     */
    public final int        getVersion()
    {
        return version;
    }

    /**
     * @inheritDoc
     * @exclude
     */
    public final void       setVersion( final int version )
    {
        this.version = version;
    }

    /**
     * Called by <code>ComponentProcessView</code>
     * @inheritDoc
     * @exclude
     */
    public final void       setVersion()
    {
        if( isChanged() )
            incrementVersion();
    }

    /**
     * Return the unique ID for this <code>Component</code>. IDs are globally unique.
     * @return The unique ID for this <code>Component</code>.
     */
    public final long       getId()
    {
        return id;
    }

    /**
     * Do not call. Should only be used when unmarshalling a <code>Component</code>
     * @param id <code>Component</code> ID.
     * @exclude
     */
    public void             setId( final long id )
    {
        this.id = id;
    }

    /**
     * Returns <code>true</code> if this <code>Component</code> was changed during a method invocation.
     * @return <code>true</code> if this <code>Component</code> was changed during a method invocation.
     */
    @JSONTransient
    public boolean          isChanged()
    {
        return changed;
    }

    //
    // Subclass Constract
    //

    /**
     * A state change MUST call <code>changed()</code> so that the client will receive updated
     * <code>Component</code> state.
     */
    protected final void    notChanged()
    {
        changed = false;
    }

    protected final void    incrementVersion()
    {
        version++;
    }
}
